using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Commerce.GoogleCheckout;
using GCheckout.AutoGen;
using System.Xml;

public partial class PostHandler : System.Web.UI.Page
{

    string callData = "";
    XmlDocument doc = null;
    
    
    protected void Page_Load(object sender, EventArgs e)
    {

        callData = GetCallData();
        if (callData != string.Empty) {
            try {
                XmlDocument doc = new XmlDocument();
                doc.InnerXml = callData;
                //log the google call
                LogGoogleCall("Google has requested this page: " + doc.DocumentElement.Name);

                ProcessCallData();
            } catch(Exception x){
                LogGoogleCall("An error occurred: " + x.Message + "\r\n \r\nStack Trace: "+x.StackTrace+"\r\n\r\nThe post data is" + callData);

            }
        }
    }

    string GetCallData()
    {
        string sOut = "";
        try {
            byte[] bData = Request.BinaryRead(Request.TotalBytes);

            sOut = Crypto.DecodeBinary(bData);

            //the viewstate gets read when testing the postback
            if (sOut.Contains("VIEWSTATE"))
                sOut = "";
        } catch {

        }
        return sOut;
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        LogGoogleCall("Test "+DateTime.Now.ToString());
    }
    void LogGoogleCall(string sMessage)
    {

        sMessage = "Logged " + DateTime.Now.ToString() + "**************************\r\n"+sMessage;
        string logPath=Server.MapPath("google_log.txt");
        string fileText=Utility.GetFileText(logPath);
        fileText = sMessage + "\r\n" + fileText;
        Utility.WriteToFile(logPath, fileText);
    }

    /// <summary>
    /// This method processes the notification calls from Google
    /// </summary>
    void ProcessCallData()
    {
        string orderGUID = "";
        //this is a HACK. GoogleCheckout changed around the merchant-private-data 
        System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("(?<=<orderguid>).*?(?=</orderguid)");
        orderGUID = reg.Match(callData).Value;

        //read in the XML
        if (callData.Contains("<new-order-notification")) {

            //pull out the order number

            //get the order info from the calling XML stream
            NewOrderNotification newOrder = new NewOrderNotification();

            newOrder = (NewOrderNotification)Utility.XmlToObject(newOrder.GetType(), callData);
           
            //reset the orderNumber so it matches with Google
            string googleOrderNumber = newOrder.googleordernumber;

            Commerce.Common.Order order = OrderController.GetOrder(orderGUID);
            
            //reset to the GoogleNumber
            order.OrderGUID = googleOrderNumber;

            //set the status as reviewing
            order.OrderStatus = Commerce.Common.OrderStatus.ReceivedAwaitingPayment;

            //save em
            try {
                order.Save(Utility.GetUserName());
                LogGoogleCall("new-order-notification received and saved: Order Number " + order.OrderNumber);
            } catch (Exception x) {
                LogGoogleCall("new-order-notification received and FAILED: Order Number " + order.OrderNumber+". Exception is \r\n"+x.Message);

            }


        } else if (callData.Contains("<order-state-change-notification")) {

            //this will be where Google tells the site the order has been shipped.
            OrderStateChangeNotification changeOrder = new OrderStateChangeNotification();
            changeOrder = (OrderStateChangeNotification)Utility.XmlToObject(changeOrder.GetType(), callData);
            FinancialOrderState orderState = changeOrder.newfinancialorderstate;
            //the state order goes this way:
            //NEW - REVIEWING
            //NEW - CHARGEABLE
            //PROCESSING - CHARGING
            //PROCESSING - CHARGED
            //WILL_NOT_DELIVER - PAYMENT_DECLINED
            //WILL_NOT_DELIVER - CANCELLED
            //WILL_NOT_DELIVER - CANCELLED_BY_GOOGLE

            //the only thing we're interested in, since this is a Level 1 integration
            //is when the order is under review, charged, or cancelled
            
            //pull the order out
            Commerce.Common.Order order = OrderController.GetOrder(changeOrder.googleordernumber);
            if (order != null) {
                if (orderState == FinancialOrderState.REVIEWING) {
                    //the order was recieved, set as awaiting payment
                    order.OrderStatus = Commerce.Common.OrderStatus.ReceivedAwaitingPayment;
                    //save it
                    try {
                        order.Save(Utility.GetUserName());
                        LogGoogleCall("Order status set to REVIEWING from Google: Order Number " + order.OrderNumber);
                    } catch (Exception x) {
                        LogGoogleCall("Order Status Change (Reviewing) received and FAILED: Order Number " + order.OrderNumber + ". Exception is \r\n" + x.Message);

                    }
                }else if (orderState==FinancialOrderState.CHARGED) {

                    //add a note
                    Commerce.Common.OrderNote note = new Commerce.Common.OrderNote();
                    note.OrderID = order.OrderID;
                    note.Note = "Payment notice received from Google - " + changeOrder.serialnumber;
                    note.OrderStatus = "Order Paid";

                    //add a transaction
                    Commerce.Common.Transaction trans = new Commerce.Common.Transaction();
                    trans.OrderID = order.OrderID;
                    trans.TransactionDate = DateTime.Now;
                    trans.TransactionNotes = "Payment from Google";

                    //if your compiler errors on this line, go to the enums (App_Code/DataAccess/Enums.cs) and
                    //add an item called "GoogleCheckout" to the TransactionType enum.
                    //then make sure to add the value (it should be 6) into the CSK_Store_TransactionType table
                    trans.TransactionType = Commerce.Common.TransactionType.GoogleCheckout;
                    trans.Amount = order.OrderTotal;
                    //save it
                    trans.Save(Utility.GetUserName());
                    
                    
                    //the order was paid, set as completed
                    order.OrderStatus = Commerce.Common.OrderStatus.ReceivedPaymentProcessingOrder;
                    //save it
                    try {
                        order.Save(Utility.GetUserName());
                        LogGoogleCall("Order status set to PAID from Google: Order Number " + order.OrderNumber);
                    } catch (Exception x) {
                        LogGoogleCall("Order Status Change (PAID) received and FAILED: Order Number " + order.OrderNumber + ". Exception is \r\n" + x.Message);

                    }
                } else if (orderState == FinancialOrderState.CANCELLED) {
                    //cancel the order
                    order.OrderStatus = Commerce.Common.OrderStatus.OrderCancelledPriorToShipping;
                    //save it
                    try {
                        order.Save(Utility.GetUserName());
                        LogGoogleCall("Order status set to CANCELLED from Google: Order Number " + order.OrderNumber);
                    } catch (Exception x) {
                        LogGoogleCall("Order Status Change (CANCELLED) received and FAILED: Order Number " + order.OrderNumber + ". Exception is \r\n" + x.Message);

                    }
                } else if (orderState == FinancialOrderState.PAYMENT_DECLINED) {
                    //if it was declined, keep the order but let the user know
                    order.OrderStatus = Commerce.Common.OrderStatus.DelayedOrderUnderReview;
                    //save it
                    try {
                        order.Save(Utility.GetUserName());
                        LogGoogleCall("Order status set to PAYMENT_DECLINED from Google: Order Number " + order.OrderNumber);
                    } catch (Exception x) {
                        LogGoogleCall("Order Status Change (PAYMENT_DECLINED) received and FAILED: Order Number " + order.OrderNumber + ". Exception is \r\n" + x.Message);

                    }

                } else if (orderState==FinancialOrderState.CANCELLED_BY_GOOGLE) {
                    //cancel the order
                    order.OrderStatus = Commerce.Common.OrderStatus.OrderCancelledPriorToShipping;
                    //save it
                    try {
                        order.Save(Utility.GetUserName());
                        LogGoogleCall("Order status set to CANCELLED_BY_GOOGLE from Google: Order Number " + order.OrderNumber);
                    } catch (Exception x) {
                        LogGoogleCall("Order Status Change (CANCELLED_BY_GOOGLE) received and FAILED: Order Number " + order.OrderNumber + ". Exception is \r\n" + x.Message);

                    }
                }

            }

        }
    }
    protected void Button1_Click1(object sender, EventArgs e)
    {
        callData = Utility.GetFileText("sample-neworder.txt");
        doc = new XmlDocument();
        doc.InnerXml = callData;
        ProcessCallData();
    }
    protected void Button2_Click(object sender, EventArgs e) {
        callData = Utility.GetFileText("sample-orderchangestate.txt");
        doc = new XmlDocument();
        doc.InnerXml = callData;
        ProcessCallData();

    }
}
